﻿using Lan.Business;
using Lan.Core;
using Lan.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LanWeb.WebApi.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class CodeController : ControllerBase
    {
        IXT_TableService Service = new XT_TableService();

        [HttpGet]
        public List<ElementSelect> GetList()
        {
            List<XT_Table> list = Service.GetList();
            List<ElementSelect> results = new();
            foreach (XT_Table item in list.OrderBy(t => t.TableName))
            {
                results.Add(new ElementSelect()
                {
                    Value = item.Id.ToString(),
                    Label = item.TableName + "(" + item.TableDescription + ")"
                });
            }
            return results;
        }

        [HttpGet]
        public XT_Table Find(Guid id)
        {
            return Service.Find(id);
        }

        /// <summary>
        /// 数据表保存
        /// </summary>
        /// <param name="model">表模型</param>
        /// <returns></returns>
        [HttpPost]
        public bool Save([FromBody] XT_Table model)
        {
            //model.Columns.Add(new XT_Column()
            //{
            //    IsKey = false,
            //    ColumnName = "Longitude",
            //    ColumnDescription = "经度",
            //    ColumnType = "decimal",
            //    DbIgnore = false,
            //    IsNull = true,
            //    MaxLength = 15,
            //    MinLength = 10,
            //    WebIgnore = false
            //});
            //model.Columns.Add(new XT_Column()
            //{
            //    IsKey = false,
            //    ColumnName = "Latitude",
            //    ColumnDescription = "纬度",
            //    ColumnType = "decimal",
            //    DbIgnore = false,
            //    IsNull = true,
            //    MaxLength = 15,
            //    MinLength = 10,
            //    WebIgnore = false
            //});
            //model.Columns.Add(new XT_Column()
            //{
            //    IsKey = false,
            //    ColumnName = "Address",
            //    ColumnDescription = "地址",
            //    ColumnType = "nvarchar",
            //    DbIgnore = false,
            //    IsNull = true,
            //    MaxLength = 100,
            //    MinLength = 2,
            //    WebIgnore = false
            //});
            //model.Columns.Add(new XT_Column()
            //{
            //    IsKey = false,
            //    ColumnName = "CreateId",
            //    ColumnDescription = "创建用户主键",
            //    ColumnType = "uniqueidentifier",
            //    DbIgnore = false,
            //    IsNull = true,
            //    MaxLength = 0,
            //    MinLength = 0,
            //    WebIgnore = false
            //});
            //model.Columns.Add(new XT_Column()
            //{
            //    IsKey = false,
            //    ColumnName = "CreateDate",
            //    ColumnDescription = "创建时间",
            //    ColumnType = "datetime",
            //    DbIgnore = false,
            //    IsNull = true,
            //    MaxLength = 0,
            //    MinLength = 0,
            //    WebIgnore = false
            //});
            //model.Columns.Add(new XT_Column()
            //{
            //    IsKey = false,
            //    ColumnName = "ModifyId",
            //    ColumnDescription = "更新用户主键",
            //    ColumnType = "uniqueidentifier",
            //    DbIgnore = false,
            //    IsNull = true,
            //    MaxLength = 0,
            //    MinLength = 0,
            //    WebIgnore = false
            //});
            //model.Columns.Add(new XT_Column()
            //{
            //    IsKey = false,
            //    ColumnName = "ModifyDate",
            //    ColumnDescription = "更新时间",
            //    ColumnType = "datetime",
            //    DbIgnore = false,
            //    IsNull = true,
            //    MaxLength = 0,
            //    MinLength = 0,
            //    WebIgnore = false
            //});

            Service.Add(model);
            return true;
        }

        /// <summary>
        /// 生成代码
        /// </summary>
        /// <param name="model">表模型</param>
        /// <returns></returns>
        [HttpPost]
        public string GenerateCode([FromBody] XT_Table model)
        {
            CreateBusiness(model);
            string sql = MssqlCreateTable(model);
            Service.CreateTable(sql);
            CreateModel(model);
            return "生成代码成功";
        }

        private void PostgresqlCreateTable(XT_Table table)
        {
            StringBuilder sql = new StringBuilder();
            sql.Append($"CREATE TABLE {table.TableName}(\r\n");
            StringBuilder decription = new StringBuilder();
            decription.Append($"COMMENT ON TABLE {table.TableName} IS '{table.TableDescription}';\r\n");

            foreach (XT_Column item in table.Columns)
            {
                sql.Append(item.ColumnName + " ");
                if (item.ColumnType == "int" && item.IsKey)
                {
                    sql.Append("SERIAL ");
                }
                else if (item.ColumnType == "DateTime")
                {
                    sql.Append($"TIMESTAMP ");
                }
                else
                {
                    sql.Append($"{item.ColumnType.ToUpper()} ");
                }

                if (item.ColumnType == "decimal")
                {
                    sql.Append($"({item.MaxLength},{item.MinLength}) ");
                }
                else if (item.ColumnType.Contains("char"))
                {
                    sql.Append($"({item.MaxLength}) ");
                }
                //else
                //{
                //    sql.Append($" ");
                //}
                if (item.IsKey) sql.Append("PRIMARY KEY ");
                sql.Append(item.IsNull ? "NULL,\r\n" : "NOT NULL,\r\n");

                decription.Append($"COMMENT ON COLUMN {table.TableName}.{item.ColumnName} ");
                decription.Append($"IS '{item.ColumnDescription}';\r\n");
            }

            sql.Remove(sql.Length - 3, 1);
            string postgresql = sql.ToString() + ");\r\n\r\n" + decription.ToString();

        }

        private string MssqlCreateTable(XT_Table table)
        {
            string sql = $"CREATE TABLE {table.TableName}(\r\n";
            string remark = $"\r\nEXEC SYS.SP_ADDEXTENDEDPROPERTY 'MS_Description','{table.TableDescription}','USER','DBO','TABLE','{table.TableName}'";

            foreach (XT_Column item in table.Columns)
            {
                sql += item.ColumnName + " " + item.ColumnType + " ";
                if (item.ColumnType.Contains("char"))
                {
                    sql += "(" + item.MaxLength + ")";
                }
                else if (item.ColumnType == "decimal")
                {
                    sql += "(" + item.MaxLength + "," + item.MinLength + ")";
                }
                if (item.IsKey) sql += "PRIMARY KEY ";
                sql += item.IsNull ? "NULL,\r\n" : "NOT NULL,\r\n";

                remark += $"\r\nEXEC SYS.SP_ADDEXTENDEDPROPERTY 'MS_Description','{item.ColumnDescription}','USER','DBO','TABLE','{table.TableName}','COLUMN','{item.ColumnName}';";
            }

            sql += ")";
            sql += remark;
            return sql;
        }

        /// <summary>
        /// 添加用户自定义表
        /// </summary>
        /// <param name="model">用户自定义表模型</param>
        [HttpPost]
        public void CreateModel(XT_Table model)
        {
            string content = FileHelper.Read("G:\\Lan\\NetCore\\LanWeb.WebApi\\Template\\Model.txt");

            StringBuilder sb = new();
            XT_Column item;
            int count = model.Columns.Count;
            for (int i = 0; i < count; i++)
            {
                item = model.Columns[i];
                sb.Append($"\t\t/// <summary>\r\n\t\t/// {item.ColumnDescription}\r\n\t\t/// </summary>\r\n");
                if (item.DbIgnore) sb.Append("\t\t[SugarColumn(IsIgnore =true)]\r\n");
                if (item.WebIgnore) sb.Append("\t\t[JsonIgnore]\r\n");
                if (item.IsKey) sb.Append("\t\t[SugarColumn(IsPrimaryKey =true)]\r\n");
                sb.Append($"\t\tpublic ");
                if (item.ColumnType == "uniqueidentifier")
                {
                    sb.Append("Guid");
                }
                else if (item.ColumnType == "datetime")
                {
                    sb.Append("DateTime");
                }
                else if (item.ColumnType.Contains("char"))
                {
                    sb.Append("string");
                }
                else if (item.ColumnType == "bit")
                {
                    sb.Append("bool");
                }
                else
                {
                    sb.Append(item.ColumnType);
                }
                sb.Append($" {item.ColumnName} {{ get; set; }}");
                if (i != count - 1) sb.Append("\r\n\r\n");
            }
            content = content.Replace("{TableName}", model.TableName)
                .Replace("{TableDescription}", model.TableDescription)
                .Replace("{ColumnInfo}", sb.ToString());
            FileHelper.WriteFileLines("F:\\3L\\01Code\\30双雁\\Toilet\\ToiletModels\\Warehouse\\Model\\" + model.TableName + ".cs", content);
        }

        [HttpPost]
        public void ModifyField(FieldSave model)
        {
            string sql = "";
            if (model.OldField.ColumnName != model.NewField.ColumnName)
            {
                sql = $"exec sp_rename 'XT_Column.{model.OldField.ColumnName}','{model.NewField.ColumnName}','column'";
            }
            //if()
        }

        [HttpPost]
        public void CreateField(XT_Column model)
        {

        }

        private void CreateBusiness(XT_Table model)
        {
            model.SolutionPath = "F:\\3L\\01Code\\30双雁\\Toilet\\";
            model.Module = "Warehouse";
            string content = FileHelper.ReadTemplate("IService.txt").Replace("{Module}", model.Module).Replace("{TableName}", model.TableName);
            FileHelper.Write(model.SolutionPath + "ToiletBusiness\\" + model.Module + "\\IService\\", "I" + model.TableName + "Service.cs", content);

            content = FileHelper.ReadTemplate("Service.txt").Replace("{Module}", model.Module).Replace("{TableName}", model.TableName);
            FileHelper.Write(model.SolutionPath + "ToiletBusiness\\" + model.Module + "\\Service\\", model.TableName + "Service.cs", content);

            content = FileHelper.ReadTemplate("IRepository.txt").Replace("{TableName}", model.TableName);
            FileHelper.Write(model.SolutionPath + "ToiletBusiness\\" + model.Module + "\\IRepository\\", "I" + model.TableName + "Repository.cs", content);

            content = FileHelper.ReadTemplate("Repository.txt").Replace("{Module}", model.Module).Replace("{TableName}", model.TableName);
            FileHelper.Write(model.SolutionPath + "ToiletBusiness\\" + model.Module + "\\Repository\\", model.TableName + "Repository.cs", content);

            content = FileHelper.ReadTemplate("Controller.txt").Replace("{Module}", model.Module)
                .Replace("{TableName}", model.TableName).Replace("{TableDescription}", model.TableDescription);
            FileHelper.Write(model.SolutionPath + "ToiletWebEntry\\Controllers\\" + model.Module + "\\", model.TableName + "Controller.cs", content);

            //content = FileHelper.ReadFile("Page.txt").Replace("{TableName}", model.TableName);
            //FileHelper.WriteFile(model.SolutionPath + "FpModels\\" + model.Module + "\\", model.TableName + "Page.cs", content);
        }

        [HttpPost]
        public void AddMethod(CreateMethod model)
        {
            CreateControllerMethod(model);
            CreateMethod(model, "Repository");
            CreateMethod(model, "Service");
            CreateInterface(model, "Repository");
            CreateInterface(model, "Service");
        }

        private void CreateInterface(CreateMethod model, string type)
        {
            string path = $"F:\\3L\\01Code\\30双雁\\Toilet\\ToiletBusiness\\Warehouse\\I{type}\\I{model.TableName + type}.cs";
            List<string> list = FileHelper.ReadFileLines(path);

            List<string> append = new()
            {
                $"\t\t",
                $"\t\t#region {model.MethodDescription}",
                "\t\t/// <summary>",
                $"\t\t/// {model.MethodDescription}",
                "\t\t/// </summary>",
                $"\t\t/// <param name=\"{model.ParamName}\">{model.ParamDescription}</param>",
                "\t\t/// <returns></returns>",
                $"\t\t{model.ReturnType} {model.MethodName}({model.ParamType} {model.ParamName});",
                "\t\t#endregion"
            };

            list.InsertRange(list.Count - 2, append);
            FileHelper.WriteFileLines(path, list);
        }

        private void CreateMethod(CreateMethod model, string type)
        {
            string path = $"F:\\3L\\01Code\\30双雁\\Toilet\\ToiletBusiness\\Warehouse\\{type}\\{model.TableName + type}.cs";
            List<string> list = FileHelper.ReadFileLines(path);

            List<string> append = new()
            {
                $"\t\t",
                $"\t\t#region {model.MethodDescription}",
                "\t\t/// <summary>",
                $"\t\t/// {model.MethodDescription}",
                "\t\t/// </summary>",
                $"\t\t/// <param name=\"{model.ParamName}\">{model.ParamDescription}</param>",
                "\t\t/// <returns></returns>",
                $"\t\tpublic {model.ReturnType} {model.MethodName}({model.ParamType} {model.ParamName})",
                "\t\t{",
                $"\t\t\treturn Repository.{model.MethodName}({model.ParamName});",
                "\t\t} ",
                "\t\t#endregion"
            };

            list.InsertRange(list.Count - 2, append);
            FileHelper.WriteFileLines(path, list);
        }

        private void CreateControllerMethod(CreateMethod model)
        {
            string http = "";
            string from = "";
            if (model.RequestType == 1)
            {
                http = "HttpGet";
                from = model.IsClass ? "[FromQuery]" : "";
            }
            else if (model.RequestType == 2)
            {
                http = "HttpPost";
                from = "[FromQuery]";
            }
            string path = $"F:\\3L\\01Code\\30双雁\\Toilet\\ToiletWebEntry\\Controllers\\Warehouse\\{model.TableName}Controller.cs";
            List<string> list = FileHelper.ReadFileLines(path);

            List<string> append = new()
            {
                "\t\t",
                $"\t\t#region {model.MethodDescription}",
                "\t\t/// <summary>",
                $"\t\t/// {model.MethodDescription}",
                "\t\t/// </summary>",
                $"\t\t/// <param name=\"{model.ParamName}\">{model.ParamDescription}</param>",
                "\t\t/// <returns></returns>",
                $"\t\t[{http}]",
                $"\t\tpublic {model.ReturnType} {model.MethodName}({from} {model.ParamType} {model.ParamName})",
                "\t\t{",
                $"\t\t\treturn Service.{model.MethodName}({model.ParamName});",
                "\t\t} ",
                "\t\t#endregion"
            };

            list.InsertRange(list.Count - 2, append);
            FileHelper.WriteFileLines(path, list);
        }

        /// <summary>
        /// 根据方法描述删除方法
        /// </summary>
        /// <param name="methodDescription">方法描述</param>
        [HttpPost]
        public void DeleteMethod(string methodDescription)
        {
            List<string> list = FileHelper.ReadFileLines("F:\\3L\\01Code\\30双雁\\Toilet\\ToiletWebEntry\\Controllers\\Warehouse\\CK_WarehouseDetailController.cs");

            int start = 0;
            int end = 0;
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].Contains(methodDescription))
                {
                    start = i;
                }

                if (start > 0 && list[i].Contains("#endregion"))
                {
                    end = i;
                }
            }

            if (start > 0 && end > 0)
            {
                list.RemoveRange(start, end - start);
            }
        }
    }

    public class CreateMethod
    {
        public string TableName { get; set; }
        public string MethodName { get; set; }
        public string MethodDescription { get; set; }
        public string ParamDescription { get; set; }
        public string ParamName { get; set; }
        public string ParamType { get; set; }
        public int RequestType { get; set; }
        public string ReturnType { get; set; }
        public bool IsClass { get; set; }
    }
}
